#pragma once
#include <string>
#include <cstring>
std::string Encode(std::string& str)
{
    size_t len = str.size();
    str = std::to_string(len) + '\n' + str + '\n';
    return str;
}


//读取报头，返回解析出的字符串
std::string Decode(std::string& str)
{
    size_t pos = str.find('\n');
    size_t len = std::stoi(str.substr(0, pos));
    //找到pos后第一个不是'\n'的位置
    while(str[pos] == '\n')
    {
        ++pos;
    }
    //解析数据
    std::string ret = str.substr(pos, len);
    if(ret.size() != len)
    {
        return nullptr;
    }

    //删除解析过的数据
    str.erase(0, pos + len + 1);
    return ret;
}



class Request
{
public:
    Request(int a = 0, int b = 0, const std::string& op = "")
        :_a(a)
        ,_b(b)
        ,_op(op)
    {}
    //非空为真
    std::string Serialize() const
    {
        if (_op_list.find(_op) == std::string::npos)
        {
            return "";
        }
        return std::to_string(_a) + " " + _op + " " + std::to_string(_b);
    }
    bool Deserialize(const std::string& str)
    {
        size_t pos = str.find(' ');
        if(pos == std::string::npos)
        {
            std::cerr << "Request deserialize fail " << std::endl;
            return false;
        }
        try
        {
            _a = std::stoi(str.substr(0, pos));
        }
        catch(const std::invalid_argument& e)
        {
            std::cerr << "Request deserialize fail " << e.what() << std::endl;
            return false;
        }
        catch (const std::out_of_range& e) 
        {
            std::cerr << "Request deserialize fail " << e.what() << std::endl;
            return false;
        }
        size_t last = pos;
        pos = str.find(' ', last + 1);
        _op = str.substr(last + 1, pos - last - 1);
        try
        {
            _b = std::stoi(str.substr(pos + 1));
        }
        catch(const std::invalid_argument& e)
        {
            std::cerr << "Request deserialize fail " << e.what() << std::endl;
            return false;
        }
        catch (const std::out_of_range& e) 
        {
            std::cerr << "Request deserialize fail" << e.what() << std::endl;
            return false;
        }
        return true;
    }


    int GetA()const
    {
        return _a;
    }


    int GetB()const
    {
        return _b;
    }


    std::string GetOp()const
    {
        return _op;
    }
private:
    int _a;
    int _b;
    std::string _op;
    static std::string _op_list;
};

std::string Request::_op_list = "+-*/%";



class Response
{
public:
    Response(int result = 0, int status = 0)
        :_result(result)
        ,_status(status)
    {}
    std::string Serialize() const
    {
        return std::to_string(_result) + " " + std::to_string(_status);
    }

    bool Deserialize(const std::string& str)
    {
        size_t pos = str.find(' ');
        if(pos == std::string::npos)
        {
            std::cerr << "Response deserialize fail" << std::endl;
            return false;
        }
        try
        {
            _result = std::stoi(str.substr(0, pos));
        }
        catch(const std::invalid_argument& e)
        {
            std::cerr << "Response deserialize fail" << e.what() << std::endl;
            return false;
        }
        catch (const std::out_of_range& e) 
        {
            std::cerr << "Response deserialize fail" << e.what() << std::endl;
            return false;
        }
        try
        {
            _status = std::stoi(str.substr(pos + 1));
        }
        catch(const std::invalid_argument& e)
        {
            std::cerr << "Response deserialize fail" << e.what() << std::endl;
            return false;
        }
        catch (const std::out_of_range& e) 
        {
            std::cerr << "Response deserialize fail" << e.what() << std::endl;
            return false;
        }
        return true;
    }
     
    int GetResult()const
    {
        return _result;
    }
    int GetStatus()const
    {
        return _status;
    }


private:
    int _result;
    int _status; 
};